package com.rustic.server.web;

import cn.hutool.core.text.CharSequenceUtil;
import cn.xy.base.server.config.AppConfig;
import cn.xy.base.server.consts.AuthConsts;
import cn.xy.base.server.utils.WebContextUtil;
import cn.xy.base.server.web.RepeatSubmitService;
import cn.xy.commons.constant.Consts;
import cn.xy.commons.enums.DisableStatus;
import cn.xy.commons.util.JwtUtil;
import cn.xy.commons.web.RequestUtil;
import com.rustic.server.po.User;
import com.rustic.server.service.UserService;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 前台业务相关拦截器
 *
 *  @author xy
 */
@Slf4j
public class WebServiceInterceptor implements HandlerInterceptor {

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private RepeatSubmitService formRepeatSubmit;

    @Autowired
    private UserService userService;

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     *
     * @param request  request
     * @param response response
     * @param handler  handler
     * @return true，如果false，停止流程，api被拦截
     */
    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            WebContextUtil.setResponse(response, Consts.NOT_FOUND, "404 not found");
            return false;
        }
        // 填充公共参数
        boolean ignoreAuth = WebContextUtil.checkIgnore(handler);
        String bearToken = RequestUtil.getToken(request, AuthConsts.FRONT_AUTHORIZATION_HEADER);
        if (CharSequenceUtil.isEmpty(bearToken) && !ignoreAuth) {
            WebContextUtil.setResponse(response, Consts.NO_LOGIN_CODE, "未登录");
            return false;
        }
        // 填充WebContext
        WebContext.clear();
        WebContext.PublicParameter publicParameter = WebContext.getPublicParameter();
        publicParameter.setIp(RequestUtil.getRemoteAddr(request));
        //忽略验证
        if (ignoreAuth && CharSequenceUtil.isEmpty(bearToken)) {
            return true;
        }
        // 检查token
        Claims claims = JwtUtil.parseJwt(appConfig.getJwtSecret(), bearToken);
        if (!ignoreAuth && JwtUtil.isExpired(claims, appConfig.getJwtSubject())) {
            WebContextUtil.setResponse(response, Consts.NO_LOGIN_CODE, "未登录");
            return false;
        }
        publicParameter.setToken(bearToken);
        // token数据解析
        int userId = JwtUtil.getInteger(claims, UserService.USER_ID);
        if (userId == 0) {
            return true;
        }
        // 阻止表单重复提交
        boolean result = formRepeatSubmit.prevent(userId, request, handler);
        if (result) {
            WebContextUtil.setResponse(response, Consts.ERROR_CODE, "请求次数频繁，请稍后再试");
            return false;
        }
        // 验证登陆信息
        boolean isLogin = userService.isLogin(userId, bearToken);
        if (!ignoreAuth && !isLogin) {
            WebContextUtil.setResponse(response, Consts.NO_LOGIN_CODE, "登录信息已失效，请重新登录");
            return false;
        }
        if (!ignoreAuth) {
            User user = userService.getById(userId);
            if (user == null) {
                WebContextUtil.setResponse(response, Consts.NO_LOGIN_CODE, "登录信息已失效，请重新登录");
                return false;
            }
            userService.renewLogin(userId);
        }
        publicParameter.setUserId(userId);
        return true;
    }

}
